package Strategy;
//策略模式：提供一组算法，将算法进行封装，使得这些算法可以相互替换，并且算法的变化不会影响使用算法的客户
//属于对象行为模式，通过对算法进行封装，把使用算法的责任和算法的实现分割，并且委派给不同的对象对这些算法进行管理
public class StrategyPattern {

    public static void main(String[] args) {
        Context context = new Context();
        Strategy strategy1 = new ConcreteStrategyA();
        Strategy strategy2 = new ConcreteStrategyB();
        context.setStrategy(strategy1);
        context.strategyMethod();
        context.setStrategy(strategy2);
        context.strategyMethod();

    }
}
//优点：
//1、多重语句不易于维护，使用策略模式可以避免使用多重条件语句
//2、提供了一系列的可供重用的算法族，恰当使用继承可以把算法族的公共代码转移到父类当中，避免重复
//3、提供了对开闭原则的完美支持，可以在不修改原代码的情况下，灵活增加新的算法
//4、提供了相同行为的不同实现，客户可以根据需求选择不同的实现
//5、把算法的使用放到环境类中，而算法的实现转移到具体策略类中，实现了二者的分离
//缺点：
//1、客户端必须理解所有的策略类，适时采用合适的策略类
//2、造成策略类过多

//注意：策略的重点在于算法的组织而不是算法的内部具体实现
/**
 * 模式结构：
 * 1、抽象策略类：（Strategy）定义了一个公共的接口，各种不同的算法以不同的方式实现这个接口，环境角色使用这个接口去调用不同的算法，一般使用接口或者抽象类进行实现
 * 2、具体策略类（Concrete Strategy类）实现了抽象策略类定义的几口，并提供具体的算法实现
 *3、 环境类：（context）持有一个策略类的引用，最终提供给客户端使用
 */

//1. 抽象策略类
interface Strategy{
    public void strategyMethod();//策略方法
}
//2. 具体策略类
class ConcreteStrategyA implements Strategy{

    @Override
    public void strategyMethod() {
        System.out.println("具体策略类A的方法使用");
    }
}
class ConcreteStrategyB implements Strategy{

    @Override
    public void strategyMethod() {
        System.out.println("具体策略类B的方法使用");
    }
}
//环境类
class Context{
    private Strategy strategy;//策略类的引用

    public Strategy getStrategy() {
        return strategy;
    }

    public void setStrategy(Strategy strategy) {
        this.strategy = strategy;
    }
    //调用策略类中的方法
    public void strategyMethod(){
        strategy.strategyMethod();
    }
}
/**
 * 策略模式的应用场景
 * 1. 策略模式在很多地方用到，如 Java SE 中的容器布局管理就是一个典型的实例，
 * Java SE 中的每个容器都存在多种布局供用户选择。在程序设计中，通常在以下几种情况中使用策略模式较多。
 * 1. 一个系统需要动态地在几种算法中选择一种时，可将每个算法封装到策略类中。
 * 1. 一个类定义了多种行为，并且这些行为在这个类的操作中以多个条件语句的形式出现，
 * 可将每个条件分支移入它们各自的策略类中以代替这些条件语句。
 * 1. 系统中各算法彼此完全独立，且要求对客户隐藏具体算法的实现细节时。
 * 1. 系统要求使用算法的客户不应该知道其操作的数据时，可使用策略模式来隐藏与算法相关的数据结构。
 * 1. 多个类只区别在表现行为不同，可以使用策略模式，在运行时动态选择具体要执行的行为。
 *
 * 策略模式的扩展
 * 在一个使用策略模式的系统中，当存在的策略很多时，客户端管理所有策略算法将变得很复杂，
 * 如果在环境类中使用策略工厂模式来管理这些策略类将大大减少客户端的工作复杂度
 */

